# 创建时间:2023/2/5 17:58
# 创建人:天霄
# 计划 :SenjoTwintail
# 文件 :DataApi.py
# 基于 Python 3.8.2
# ========================================
# 伪接口，修改游戏数据
# ========================================
from pathlib import Path
from typing import List

from sqlalchemy import select, exists, and_
from sqlalchemy.orm import aliased

from vars import *
from Common.Tools.DataBase import ConnectSQLite
from Common.Tools.DBModel import dbModel, Row
from Common import dblog


nonestr = lambda x: 'null' if x == '' else f"'{x}'"


def tuple2str(tupledata: tuple) -> str:
    """根据传入的tuple转为sql适用的带括号的字符串

    :param tupledata: 元组数据
    :return: 字符串：(1,2) 或 ('a','b')
    """
    if not tupledata:
        raise ValueError(f'必须传有效值！而传入的是【{tupledata}】')
    datatype = type(tupledata[0])
    if not all(list(map(lambda t: isinstance(t, datatype), tupledata))):
        raise ValueError(f'元组内的值类型不一致！元组为【{tupledata}】')
    if datatype is str:
        s = "','".join(tupledata)
        return f"('{s}')"
    elif datatype is int:
        s = ",".join(list(map(str, tupledata)))
        return f"({s})"
    else:
        raise ValueError(f'元组内的值类型只能为int或str！')


class DataNotExistsError(BaseException):
    """数据不存在"""


class DataExistsError(BaseException):
    """数据已存在"""


class DataNotFoundError(BaseException):
    """数据未找到"""


class _BaseApi:
    def __init__(self):
        """数据库操作"""
        self.SQLite = ConnectSQLite(str(CONST.PATH.DATABASE_PATH))

    def close_cursor(self):
        """关闭游标"""
        self.SQLite.close_cursor()

    @staticmethod
    def GetRole(job: str = None, sex: int = None) -> list[dbModel.role]:
        """获取角色

        :param job: 默认无筛选。hero/boss/soldier/npc
        :param sex: 默认无筛选。1男2女3其他0未知，-1男+女
        :return:
        """
        with dbModel.withConnect() as sess:
            return sess.query(dbModel.role).filter(
                dbModel.role.job == job if job else True,
                dbModel.role.sex == sex if sex != -1 else dbModel.role.sex in (1, 2)
            ).all()

    @staticmethod
    def GetCode(code_type=None, has_text=None, has_img=None, has_sound=None, suit=None, status=1) -> list[dbModel.role_code]:
        """筛选获得代号

        :param code_type: 1有立绘的，2半身，3头像，0无
        :param status: 1实装，0未实装
        :param has_text: 1/0是否有文字图片
        :param has_img: 1/0是否有人物图片
        :param has_sound: 1/0是否有声音文件
        :param suit: 套装
        :return:
        """
        with dbModel.withConnect() as sess:
            return sess.query(dbModel.role_code).filter(
                dbModel.role_code.status == status if status is not None else True,
                dbModel.role_code.code_type == code_type if code_type is not None else True,
                dbModel.role_code.has_text == has_text if has_text is not None else True,
                dbModel.role_code.has_img == has_img if has_img is not None else True,
                dbModel.role_code.has_sound == has_sound if has_sound is not None else True,
                dbModel.role_code.suit == suit if suit is not None else True
            ).all()

    @staticmethod
    def GetSoldierByAnyCode(anyCode) -> list[Row[dbModel.role_code, dbModel.soldier]]:
        """根据任意code获取唯一的原版军士（1条），空则返回所有（多条）

        :param anyCode: 任意code
        :return:
        """
        with dbModel.withConnect() as sess:
            return sess.query(dbModel.role_code, dbModel.soldier).filter(
                dbModel.role_code.role_id == dbModel.soldier.role_id,
                dbModel.role_code.code == dbModel.soldier.code if anyCode is None else dbModel.role_code.code == anyCode,
                dbModel.soldier.main == 1
            ).all()

    @staticmethod
    def GetTheCode(code) -> list[dbModel.role_code]:
        """判断code是否存在，若存在则返回该条数据"""
        with dbModel.withConnect() as sess:
            return sess.query(dbModel.role_code).filter(dbModel.role_code.code == code).all()

    @staticmethod
    def GetCodeByClothcode(clothcode: str) -> list[Row[dbModel.role_code, dbModel.soldier]]:
        """根据服装code获取其soldier表的code，无则返回空"""
        with dbModel.withConnect() as sess:
            return sess.query(dbModel.role_code, dbModel.soldier).filter(
                dbModel.role_code.role_id == dbModel.soldier.role_id,
                dbModel.role_code.code == clothcode
            ).group_by(dbModel.role_code.code).all()

    @staticmethod
    def GetInfoByCode(code: str) -> list[Row[dbModel.role_code, dbModel.role]]:
        """根据code获取军士所有信息"""
        with dbModel.withConnect() as sess:
            return sess.query(dbModel.role_code, dbModel.role).filter(
                dbModel.role_code.role_id == dbModel.role.role_id,
                dbModel.role_code.code == code
            ).all()

    @staticmethod
    def GetCharimage(code, imgtype=(), job='', nature='', face='', facenum='', mode='clothes') -> list[dbModel.charimage]:
        """获取一个军士的图片数据

        :param code: 图片的军士代号
        :param imgtype: 图片类型，支持多个
        :param job: 职业
        :param nature: 性质
        :param face: 表情
        :param facenum: 表情序号
        :param mode: 搜索模式（按soldier/clothes的code搜，后者只有1个结果）
        :return: charimage.*
        """
        if mode not in ('soldier', 'clothes'):
            raise KeyError(f'模式错误！只能为soldier/clothes，然而传入的是{mode}')
        with dbModel.withConnect() as sess:
            if mode == 'clothes':
                return sess.query(dbModel.charimage).filter(
                    dbModel.charimage.code == code,
                    dbModel.charimage.imgtype.in_(imgtype) if imgtype else True,
                    dbModel.charimage.job == job if job else True,
                    dbModel.charimage.nature == nature if nature else True,
                    dbModel.charimage.face == face if face else True,
                    dbModel.charimage.facenum == facenum if facenum else True,
                    dbModel.charimage.status == 1,
                ).all()
            elif mode == 'soldier':
                return [row[0] for row in
                    sess.query(dbModel.charimage, dbModel.role_code, dbModel.soldier).filter(
                    dbModel.charimage.code_id == dbModel.role_code.code_id,
                    dbModel.role_code.role_id == dbModel.soldier.role_id,
                    dbModel.soldier.code == code,
                    dbModel.charimage.imgtype.in_(imgtype) if imgtype else True,
                    dbModel.charimage.job == job if job else True,
                    dbModel.charimage.nature == nature if nature else True,
                    dbModel.charimage.face == face if face else True,
                    dbModel.charimage.facenum == facenum if facenum else True,
                    dbModel.charimage.status == 1,
                ).all()]

    @staticmethod
    def GetAllSkinCharimage(code, isLinkSound=0, imgtype=(), mode='clothes') -> list[dbModel.charimage]:
        """获取一个军士的所有皮肤的所有图像

        :param code: 军士代号
        :param isLinkSound: 筛选是否关联了声音，默认0不筛选，1关联了有效声音，2关联了无效声音，3关联了任何声音，4未关联任何声音
        :param imgtype: 图片类型，支持多个
        :param mode: 搜索模式（按soldier/clothes的code搜）
        :return: (image_id, file, nature, code, imgtype, face, facenum, describe)
        """
        if mode not in ('soldier', 'clothes'):
            raise KeyError(f'模式错误！只能为soldier/clothes，然而传入的是{mode}')

        with dbModel.withConnect() as sess:
            isLinkSound_filter = lambda: True
            if isLinkSound == 0:
                pass
            elif isLinkSound == 1:
                isLinkSound_filter = lambda: sess.query(dbModel.sound_face).filter(
                    dbModel.sound_face.image_id == dbModel.charimage.image_id,
                    dbModel.sound_face.valid_flag==1).exists()
            elif isLinkSound == 2:
                isLinkSound_filter = lambda: sess.query(dbModel.sound_face).filter(
                    dbModel.sound_face.image_id == dbModel.charimage.image_id,
                    dbModel.sound_face.valid_flag==0).exists()
            elif isLinkSound == 3:
                isLinkSound_filter = lambda: sess.query(dbModel.sound_face).filter(
                    dbModel.sound_face.image_id == dbModel.charimage.image_id).exists()
            elif isLinkSound == 4:
                isLinkSound_filter = lambda: ~sess.query(dbModel.sound_face).filter(
                    dbModel.sound_face.image_id == dbModel.charimage.image_id).exists()
            if mode == 'clothes':
                return [row[0] for row in
                    sess.query(dbModel.charimage, dbModel.role_code).filter(
                    dbModel.role_code.code_id == dbModel.charimage.code_id,
                    dbModel.charimage.code == code,
                    dbModel.charimage.imgtype.in_(imgtype) if imgtype else True,
                    dbModel.charimage.status == 1
                    ).filter(isLinkSound_filter()
                ).all()]
            elif mode == 'soldier':
                return [row[0] for row in
                    sess.query(dbModel.charimage, dbModel.role_code, dbModel.soldier).filter(
                    dbModel.role_code.code_id == dbModel.charimage.code_id,
                    dbModel.soldier.role_id == dbModel.role_code.role_id,
                    dbModel.soldier.code == code,
                    dbModel.charimage.imgtype.in_(imgtype) if imgtype else True,
                    dbModel.charimage.status == 1
                    ).filter(isLinkSound_filter()
                ).all()]

    @staticmethod
    def GetAllHalfHeads(codes=()) -> list[Row[dbModel.charimage, dbModel.role_code, dbModel.role]]:
        """获取所有军士半身头像"""
        with dbModel.withConnect() as sess:
            return sess.query(dbModel.charimage, dbModel.role_code, dbModel.role).filter(
                dbModel.charimage.code_id == dbModel.role_code.code_id,
                dbModel.role_code.role_id == dbModel.role.role_id,
                dbModel.role.role_id != 99,
                dbModel.role_code.code_type.in_((1, 2)),
                dbModel.charimage.imgtype == 'halfhead',
                dbModel.charimage.status == 1,
                dbModel.charimage.code.in_(codes) if codes else True
            ).order_by(dbModel.charimage.job, dbModel.role_code.role_id
            ).all()

    @staticmethod
    def GetSoundByAnyCode(code, language, scene='', favor_type='', event='', nature='',
                          way='', num='') -> list[dbModel.sound]:
        """获取声音数据

        :param code: 声音的军士代号
        :param language: 语言
        :param scene: 场景（favor/char/battle等）
        :param favor_type: daily/gift/touch
        :param event: 事件（get/touch等）
        :param nature: 性质（h/s/soldier等）
        :param way: 方式或位置（head/oppai/hello/kanban/lv等）
        :param num: 序号或等级（gift中1为最喜欢）
        :return: sound.*
        """
        with dbModel.withConnect() as sess:
            c1 = aliased(dbModel.role_code, name='c1')
            c2 = aliased(dbModel.role_code, name='c2')

            way_filter = lambda: True
            if way == 'null':
                way_filter = lambda: dbModel.sound.way.is_(None)
            elif way == 'not_lv':
                way_filter = lambda: dbModel.sound.way != 'lv'
            elif way:
                way_filter = lambda: dbModel.sound.way == way
            return sess.query(dbModel.sound).join(c1, dbModel.sound.code_id == c1.code_id
                ).join(c2, c1.role_id == c2.role_id).filter(
                c2.code == code,
                dbModel.sound.language == language,
                dbModel.sound.scene == scene if scene else True,
                dbModel.sound.favor_type == favor_type if favor_type else True,
                dbModel.sound.event == event if event else True,
                dbModel.sound.nature == nature if nature else True,
                way_filter(),
                dbModel.sound.num == num if num else True
            ).order_by(dbModel.sound.num, dbModel.sound.sound_id).all()

    @staticmethod
    def GetTheClothIconPath(cloth_codes: tuple) -> list[tuple[str, str]]:
        """通过服装code获取对应服装icon路径

        :param cloth_codes: 服装code元组
        :return:
        """
        with dbModel.withConnect() as sess:
            return sess.query(dbModel.role_code.code, dbModel.icon.path).filter(
                dbModel.role_code.cloth_icon_id == dbModel.icon.icon_id,
                dbModel.role_code.code.in_(cloth_codes),
            ).order_by(dbModel.role_code.role_id
            ).all()

    @staticmethod
    def GetAllTheClothesIconPath(cloth_code) -> list[tuple[str, str]]:
        """通过一个服装code获取该角色所有服装icon路径

        :param cloth_code:
        :return:
        """
        with dbModel.withConnect() as sess:
            c1 = aliased(dbModel.role_code, name='c1')
            c2 = aliased(dbModel.role_code, name='c2')
            return sess.query(c2.code, dbModel.icon.path).join(c1, c1.role_id == c2.role_id).join(
                    dbModel.icon, c2.cloth_icon_id == dbModel.icon.icon_id
                ).filter(c1.code == cloth_code
                ).order_by(c2.code_id).all()

    @staticmethod
    def GetRoleRecordContent(role_id, record_type) -> list[Row[dbModel.role_record, dbModel.content]]:
        """获取角色记录文本

        :param role_id: 角色ID
        :param record_type: 类型（1犯罪记录，2角色故事，3私密记事）
        :return:[(role_rec_id, role_id, record_type, title, content_id, tt.content),()]
        """
        with dbModel.withConnect() as sess:
            return sess.query(dbModel.role_record, dbModel.content).filter(
                dbModel.role_record.content_id == dbModel.content.content_id,
                dbModel.role_record.role_id == role_id,
                dbModel.role_record.record_type == record_type,
            ).all()

    @staticmethod
    def GetRoleRecordContentByCode(code, record_type) -> list[Row[dbModel.role_record, dbModel.content]]:
        """获取角色记录文本

        :param code: 任意code
        :param record_type: 类型（1犯罪记录，2角色故事，3私密记事）
        :return:[(role_rec_id, role_id, record_type, title, content_id, tt.content),()]
        """
        with dbModel.withConnect() as sess:
            return sess.query(dbModel.role_record, dbModel.content).join(
                dbModel.role_code, dbModel.role_record.role_id == dbModel.role_code.role_id).filter(
                dbModel.role_record.content_id == dbModel.content.content_id,
                dbModel.role_code.code == code if code is not None else dbModel.role_code.code.is_(None),
                dbModel.role_record.record_type == record_type,
            ).all()

    def SetCodeHas(self, code, which, flag):
        """更改code是否含有img/text/sound

        :param code: 更改的code
        :param which: img/text/sound
        :param flag: 1/0
        :return:
        """
        if which not in ("img", "text", "sound"):
            raise KeyError(f'code只能为img/text/sound！而传入了【{code}】。')
        if flag not in (1, 0):
            raise KeyError(f"flag只能为1或0！而传入了【{flag}】")
        exists = self.GetTheCode(code)
        if not exists:
            raise DataNotExistsError(f'【{code}】不存在！')
        sql = f"""update role_code 
            set has_{which} = {flag}
            where code = "{code}" """
        return self.SQLite.update(sql)

    def LinkSoundFace(self, sound_id, image_id, valid_flag=1):
        """将声音与图片关联

        :param sound_id: 声音ID
        :param image_id: 图片ID
        :param valid_flag: 1正确的关联，0错误的关联
        :return:
        """
        sql = f"insert into sound_face(sound_id, image_id, valid_flag) values ({sound_id}, {image_id}, {valid_flag})"
        return self.SQLite.insert(sql)

    def AddRoleRecordContent(self, role_id, content, content_type, record_type, title=None):
        """添加角色记录的文本

        :param role_id: 角色ID
        :param content: 文本内容
        :param content_type: 文本类型（1犯罪记录，2角色故事，3私密记事，4语音文本）
        :param record_type: 角色记录类型（1犯罪记录，2角色故事，3私密记事）
        :param title: 标题，默认空
        :return:
        """
        if content_type in (1, 2):
            exists = self.GetRoleRecordContent(role_id, content_type)
            if exists:
                raise DataExistsError(f'已存在该类型的记录！存在的记录为【{exists}】')
        addcontent_sql = f"""insert into content(type, content) values({content_type}, '{content}')"""
        result1 = self.SQLite.insert(addcontent_sql)
        content_id = result1.get('data')
        dblog.info(f'AddRoleRecordContent add content结果：{result1}')
        if title is None: title = ''
        addrole_rec_sql = f"""insert into role_record(role_id, record_type, title, content_id) 
                    values ({role_id}, {record_type}, {nonestr(title)}, {content_id})"""
        result2 = self.SQLite.insert(addrole_rec_sql)
        dblog.info(f'AddRoleRecordContent add role_rec结果：{result2}')
        return result2

    def UpdateRoleRecordContent(self, role_rec_id, content, title=None):
        """修改角色记录的文本

        :param role_rec_id: 角色ID
        :param content: 文本内容
        :param title: 标题，默认空
        :return:
        """
        if title is not None:
            updaterole_rec_sql = f"""update role_record set title={nonestr(title)}
                    where role_rec_id={role_rec_id} """
            result1 = self.SQLite.update(updaterole_rec_sql)
            dblog.info(f'UpdateRoleRecordContent update title结果：{result1}')
        updatecontent_sql = f"""update content
                set content={nonestr(content)} 
                where content_id = (select content_id from role_record 
                        where role_rec_id={role_rec_id}) """
        result2 = self.SQLite.update(updatecontent_sql)
        dblog.info(f'UpdateRoleRecordContent update content结果：{result2}')
        return result2

    def InsertCharImage(self, job, image_infos: list):
        """新建图片"""
        sql = """insert into charimage(code_id, file, job, nature, code, imgtype, face, facenum) 
            values """
        values = list()
        for info in image_infos:
            info: dict
            file = info['file']
            nature = info['nature']
            code = info['code']
            imgtype = info['imgtype']
            face = info['face']
            facenum = info['facenum']
            if not face:
                face, facenum = 'null', 'null'
            else:
                face = f"'{face}'"
            values.append(f"""((select t.code_id from role_code t where t.code = "{code}"),"{file}","{job}","{nature}","{code}","{imgtype}",{face},{facenum})""")
        sql += ',\n'.join(values)
        # print(sql)
        return self.SQLite.insert(sql)

    def InsertTextImg(self, text_infos: list):
        """新建文字图片"""
        sql = """insert into text_img(code_id, file, vertical, nature, code) 
            values """
        values = list()
        for info in text_infos:
            info: dict
            file = info['file']
            vertical = info['vertical']
            nature = info['nature']
            code = info['code']
            values.append(f"""((select t.code_id from role_code t where t.code = "{code}"),"{file}","{vertical}","{nature}","{code}")""")
        sql += ',\n'.join(values)
        # print(sql)
        return self.SQLite.insert(sql)

    def InsertSound(self, sound_infos: list):
        """新建声音文件记录"""
        sql = """insert into sound(code_id,language,path,scene,favor_type,file,event,nature,code,way,num,describe)
            values """
        values = list()
        for info in sound_infos:
            info: dict
            file = nonestr(info['file'])
            language = nonestr(info['language'])
            path = nonestr(info['path'])
            scene = nonestr(info['scene'])
            favor_type = nonestr(info['favor_type'])
            code = nonestr(info['code'])
            event = nonestr(info['event'])
            nature = nonestr(info['nature'])
            way = nonestr(info['way'])
            num = nonestr(info['num'])
            values.append(f"""((select t.code_id from role_code t where t.code={code}),{language},{path},{scene},{favor_type},{file},{event},{nature},{code},{way},{num},(select c.describe from role_code c where c.code={code}))""")
        sql += ',\n'.join(values)
        # print(sql)
        return self.SQLite.insert(sql)

    def InsertIcon(self, type, nature, path):
        """新建icon"""
        sql = f"""insert into icon (type, nature, path) values ('{type}', '{nature}', '{path}') """
        return self.SQLite.insert(sql)


class OpenApi:
    """提供调用的API"""
    def __init__(self):
        self._apis = _BaseApi()

    def close_cursor(self):
        """关闭游标"""
        self._apis.close_cursor()

    def getCodeByClothcode(self, code) -> str | None:
        """通过任意code获取其soldier code"""
        code = self._apis.GetCodeByClothcode(code)
        if not code: return None
        return code[0][1].code

    def getInfoByCode(self, code):
        """根据code获取军士信息"""
        infos = self._apis.GetInfoByCode(code)
        if not infos: return None
        info: dict = infos[0][1].to_dict()
        none1 = lambda x: '敬请期待' if x is None else x
        none2 = lambda x: '(暂无资料)' if x is None else x
        return {k: none1(v) if k in ('cv_cn', 'cv_jp') else none2(v) for k, v in info.items()}

    def getAllSkinCharimage(self, code, isLinkSound=0, imgtype=(), mode='clothes') -> list[dbModel.charimage]:
        """获取一个军士所有皮肤的所有图像

        :param code: 军士代号
        :param isLinkSound: 筛选是否关联了声音，默认0不筛选，1关联了有效声音，2关联了无效声音，3关联了任何声音，4未关联任何声音
        :param imgtype: 图片类型，支持多个
        :return: (image_id, file, nature, code, imgtype, face, facenum, describe)
        """
        data = self._apis.GetAllSkinCharimage(code, isLinkSound, imgtype, mode)
        return data

    def getPathsCharimage(self, code, imgtype=(), job='', nature='', face='', facenum='', mode='clothes'):
        """获取图片文件的路绝对径

        :param code: 图片的军士代号
        :param imgtype: 图片类型支持多个
        :param job: 职业
        :param nature: 性质
        :param face: 表情
        :param facenum: 表情序号
        :return: 路径list
        """
        data = self._apis.GetCharimage(code, imgtype, job, nature, face, facenum, mode)
        if not data: return None
        return [CONST.PATH.CHARIMAGE_ROOT / f'{f.file}.png' for f in data]

    def getAllHalfHead(self, codes=()) ->  list[tuple[str, Path, str, str, str]] | None:
        """获取半身头像"""
        if codes is None: codes = ()
        data = self._apis.GetAllHalfHeads(codes)
        if not data: return None
        return [(f[2].name, CONST.PATH.CHARIMAGE_ROOT / f'{f[0].file}.png', f[0].code, f[0].job, f[0].nature) for f in data]

    def getTouchSound(self, code, language, way='', num='') -> list[dbModel.sound]:
        """获取声音数据

        :param code: 声音的军士代号
        :param language: 语言
        :param way: 位置（head/oppai）
        :param num: 序号
        :return:
        """
        data = self._apis.GetSoundByAnyCode(code, language, favor_type='touch', way=way, num=num)
        return data

    def getGiftSound(self, code, language, num='') -> list[dbModel.sound]:
        """获取礼物声音数据

        :param code: 声音的军士代号
        :param language: 语言
        :param num: 1~4,最喜欢到最讨厌
        :return:
        """
        data = self._apis.GetSoundByAnyCode(code, language, favor_type='gift', num=num)
        return data

    def getDailySound(self, code, language, way='not_lv', num='') -> list[dbModel.sound]:
        """获取日常声音数据

        :param code: 声音的军士代号
        :param language: 语言
        :param way: kanban/hello/lv/空等
        :param num: 序号
        :return:
        """
        data = self._apis.GetSoundByAnyCode(code, language, favor_type='daily', way=way, num=num)
        return data

    def getPathGetSound(self, code, language):
        """获取“获得”声音路径

        :param code: 声音的军士代号
        :param language: 语言
        :return: str路径
        """
        data = self._apis.GetSoundByAnyCode(code, language, scene='char', event='get')
        if not data: return None
        return CONST.PATH.SOUND_ROOT / data[0].path

    def getClothesIconPath(self, cloth_code):
        """获取服装图标路径

        :param cloth_code: 服装code，元组或字符串
        :return: [(code,path),(code,path)]
        """
        if isinstance(cloth_code, tuple):
            data = self._apis.GetTheClothIconPath(cloth_code)
        elif isinstance(cloth_code, str):
            data = self._apis.GetAllTheClothesIconPath(cloth_code)
        else: raise ValueError(f'cloth_code类型有误！只能为tuple或str！然而是【{type(cloth_code)}】')
        if not data: return None
        return [(c, CONST.PATH.ICON_ROOT / p) for c, p in data]

    def getRoleCodeByCode(self, anyCode):
        """根据任意code获取唯一的原版军士（1条），空则返回所有（多条）"""
        data = self._apis.GetSoldierByAnyCode(anyCode)
        if not data: raise DataNotExistsError(f'返回数据为空！code：{anyCode}')
        if len(data) > 1: raise ValueError('返回数据条数大于1！')
        return data[0][1].code

    def getRoleRecordContentByCode(self, anyCode, record_type):
        """获取角色的犯罪记录、角色故事

        :param anyCode: 任意code
        :param record_type: 1犯罪记录，2角色故事，3私密记事（暂无）
        :return: 查询结果：[(role_rec_id, role_id, record_type, title, content_id, tt.content),()]
        """
        data = self._apis.GetRoleRecordContentByCode(anyCode, record_type)
        return data


if __name__ == '__main__':
    # r = _BaseApi().GetInfoByCode('af')  #[(3, '爱芙', 'soldier', 2, '有', '近藤玲奈', '？', '？', '？', 'A', 170, 54, 'C', '思考', '看不清未来哪有梦想', '红色的任何东西', '不告诉你', '指挥官先生')]
    # print(type(r[0][1]), r[0][1].to_dict())
    r = _BaseApi().GetSoundByAnyCode('myzaf','jp',favor_type = 'touch'
                                # ('half',),
                                       # mode='soldier'
                                       )
    print(type(r), len(r), [i.to_dict() for i in r])
    # for one in _BaseApi.GetRole('hero', 2):
    #     print(dbModel.to_dict(one))
    # print(type(_BaseApi.GetSoldierByAnyCode('a.f')))
    # for one in _BaseApi.GetSoldierByAnyCode('af'):
    #     # print(dbModel.to_dict(one))
    #     print(one[0].to_dict())
    # r = OpenApi().getRoleCodeByCode(None)#('adf1stan')
    # print(r)
